home *** CD-ROM | disk | FTP | other *** search
- ''
- '' $Id: HBMsg.bas,v 1.2 1994/05/10 14:46:07 alex Rel $
- ''
- '' Simple BASIC Message Browser AREXX host
- ''
- '' (c) Copyright 1994 HiSoft
- ''
-
- REM $NOWINDOW
-
- DEFINT A-Z
-
- 'REM $INCLUDE Exec.bh
- 'REM $INCLUDE DOS.bh
- 'REM $INCLUDE Locale.bh
- 'REM $INCLUDE Layers.bh
- 'REM $INCLUDE Hardware.bc
- 'REM $INCLUDE Graphics.bh
- 'REM $INCLUDE Input.bc
- 'REM $INCLUDE KeyMap.bh
- 'REM $INCLUDE Intuition.bh
- 'REM $INCLUDE Icon.bh
- 'REM $INCLUDE Workbench.bc
- 'REM $INCLUDE Rexx.bh
- 'REM $INCLUDE Utility.bc
-
- DIM SHARED pool&, tl&(40), junk&
-
- REM $INCLUDE BLib/ExecSupport.bas
- REM $INCLUDE BLib/PoolSupport.bas
- REM $INCLUDE BLib/GfxMacros.bas
- REM $INCLUDE BLib/BusyPointer.bas
-
- LIBRARY OPEN "exec.library", 36
- LIBRARY OPEN "dos.library", 36
- LIBRARY OPEN "layers.library", LIBRARY_MINIMUM&
- LIBRARY OPEN "graphics.library", LIBRARY_MINIMUM&
- LIBRARY OPEN "keymap.library", 36
- LIBRARY OPEN "intuition.library", 36
- LIBRARY OPEN "icon.library", 36
- LIBRARY OPEN "rexxsyslib.library", LIBRARY_MINIMUM&
-
- ' options stuff (must match the template!)
- CONST OPT_PUBSCREEN = 0
- CONST OPT_PORTNAME = 1
- DIM SHARED opts&(1) ' number of options
-
- CONST PROP_LGAP_LOWRES = 3 ' offset from right border start
- CONST PROP_RGAP_LOWRES = 3 ' from right edge of window
- CONST PROP_LGAP_MEDRES = 4 ' offset from right border start
- CONST PROP_RGAP_MEDRES = 4 ' from right edge of window
-
- CONST PROP_TGAP = 2 ' offset from bottom border start
- CONST PROP_BGAP = 2 ' from bottom edge of window
-
- CONST PROP_VGAP = 1 ' between window border and gadget
-
- FUNCTION createRXPort&(BYVAL pName&)
- STATIC portName&, port&
-
- createRXPort& = NULL&
- ' allocate name space + space for pending replies counter
- portName& = LibAllocVecPooled&(pool&, LEN(PEEK$(pName&)) + 1 + 4)
- IF portName& <> NULL& THEN
- CopyMem pName&, portName& + 4, LEN(PEEK$(pName&)) + 1
- port& = CreateMsgPort& ' create the message port before the Forbid
- IF port& THEN
- POKEL portName&, 0 ' number of pending replies at this port
- POKEL port& + mp_Node + ln_Name, portName& + 4
- POKEB port& + mp_Node + ln_Pri, 0
- Forbid ' stop anything happening on the public port list
- IF FindPort&(portName&) = NULL& THEN
- AddPort port&
- Permit
- createRXPort& = port&
- ELSE
- Permit
- LibFreeVecPooled pool&, portName&
- DeleteMsgPort port&
- END IF
- ELSE
- LibFreeVecPooled pool&, portName&
- END IF
- END IF
- END FUNCTION
-
- FUNCTION parseRXArgs&(rxArg$, rxTemplate$, BYVAL prxArg&)
- STATIC rda&, csb$
-
- parseRXArgs& = NULL&
- rda& = AllocDosObject&(DOS_RDARGS&, NULL&)
- IF rda& <> NULL& THEN
- csb$ = rxArg$ + CHR$(10) + CHR$(0) ' build input string (with \n for bug)
- POKEL rda& + RDA_Source + CS_Buffer, SADD(csb$)
- POKEL rda& + RDA_Source + CS_Length, LEN(csb$)
- POKEL rda& + RDA_Source + CS_CurChr, 0
- POKEL rda& + RDA_DAList, NULL&
- POKEL rda& + RDA_Buffer, NULL&
- POKEL rda& + RDA_Flags, RDAF_NOPROMPT&
-
- IF ReadArgs&(SADD(rxTemplate$ + CHR$(0)), prxArg&, rda&) <> NULL& THEN
- parseRXArgs& = rda& ' success return the ReadArgs context
- ELSE
- FreeArgs rda&
- FreeDosObject DOS_RDARGS&, rda&
- END IF
- END IF
- END FUNCTION
-
- SUB disposeRXArgs(BYVAL rda&)
- IF rda& <> NULL& THEN
- FreeArgs rda&
- FreeDosObject DOS_RDARGS&, rda&
- END IF
- END SUB
-
- SUB disposeRXCommand(BYVAL port&, BYVAL rxMsg&)
- ' decrement number of replies pending at this port
- POKEL PEEKL(port& + mp_node + ln_Name) - 4, _
- PEEKL(PEEKL(port& + mp_node + ln_Name) - 4) - 1
- IF PEEKL(rxMsg& + rm_Result1) = 0 AND PEEKL(rxMsg& + rm_Result2) THEN
- DeleteArgstring PEEKL(rxMsg& + rm_Result2)
- END IF
-
- DeleteArgstring PEEKL(rxMsg& + rm_Args)
- DeleteRexxMsg rxMsg&
- END SUB
-
- FUNCTION issueRXCommand&(BYVAL port&, cmd$, ext$)
- STATIC rxMsg&, rxArgs&, rxPort&
-
- issueRXCommand& = NULL&
-
- ' create a REXX message context
- rxMsg& = CreateRexxMsg&(port&, SADD(ext$ + CHR$(0)), PEEKL(port& + mp_Node + ln_Name))
- IF rxMsg& <> NULL& THEN
- ' get a REXX arg string
- rxArgs& = CreateArgstring&(SADD(cmd$ + CHR$(0)), LEN(cmd$))
- IF rxArgs& <> NULL& THEN
- POKEL rxMsg& + rm_Action, RXCOMM& OR RXFF_RESULT&
- POKEL rxMsg& + rm_Stdin, xInput&
- POKEL rxMsg& + rm_Stdout, xOutput&
- POKEL rxMsg& + rm_Args, rxArgs&
- Forbid
- rxPort& = FindPort&(SADD("REXX" + CHR$(0)))
- IF rxPort& <> NULL& THEN
- PutMsg rxPort&, rxMsg&
- Permit
-
- ' increment number of replies pending at this port
- POKEL PEEKL(port& + mp_node + ln_Name) - 4, _
- PEEKL(PEEKL(port& + mp_node + ln_Name) - 4) + 1
- issueRXCommand& = rxMsg&
- ELSE
- Permit
- DeleteArgString rxArgs&
- DeleteRexxMsg rxMsg&
- END IF
- ELSE
- DeleteRexxMsg rxMsg&
- END IF
- END IF
- END FUNCTION
-
- SUB disposeRXPort(BYVAL port&)
- STATIC msg&
-
- RemPort port&
- ' wait for all pending messages to return
- WHILE PEEKL(PEEKL(port& + mp_node + ln_Name) - 4) <> 0
- junk& = WaitPort&(port&)
- msg& = GetMsg&(port&)
- WHILE msg& <> NULL&
- IF PEEKB(msg& + rm_Node + mn_Node + ln_Type) = NT_REPLYMSG& THEN
- disposeRXCommand port&, msg&
- ELSE
- POKEL msg& + rm_Result1, ERR10_013& ' host environment not found
- ReplyMsg msg&
- END IF
- msg& = GetMsg&(port&)
- WEND
- WEND
- LibFreeVecPooled pool&, PEEKL(port& + mp_Node + ln_Name) - 4
- DeleteMsgPort port&
- END SUB
-
- DIM SHARED errList&
-
- DIM SHARED render(RastPort_sizeof \ 2)
- DIM SHARED selren(RastPort_sizeof \ 2)
- DIM SHARED clr(RastPort_sizeof \ 2)
-
- ' view information for the error list
- DIM SHARED numLines
- DIM SHARED topLine&
- DIM SHARED linesVisible
- DIM SHARED currentLine&
-
- FUNCTION dispatchRXMsg(rxStr$)
- STATIC rxCommand$, rxArg$, rxTemplate$, n, rda&, msgNode&
-
- dispatchRXMsg = FALSE&
-
- ' Brute force and ignorance command parser... (_very_ slow)
- n = INSTR(rxStr$, " ") ' find end of command
- IF n = 0 THEN
- rxCommand$ = rxStr$ ' no space, entire string is the command
- rxArg$ = ""
- ELSE
- rxCommand$ = UCASE$(LEFT$(rxStr$, n - 1)) ' extract the command
- rxArg$ = MID$(rxStr$, n + 1) ' and arguments
- END IF
-
- IF rxCommand$ = "QUIT" THEN
- rxTemplate$ = ""
- dispatchRXMsg = TRUE&
- ELSEIF rxCommand$ = "NEWMSG" THEN
- rxTemplate$ = "UNIT/A,FILE/A,LINE/N/A,POSITION/N/A,NULL/A,ZERO/N/A,CLASS/A,ERRNUM/A/N,MESSAGE/F"
- msgNode& = LibAllocVecPooled&(pool&, Node_sizeof + 4 + 9 * 4) ' 9 template items
- IF msgNode& THEN
- rda& = parseRXArgs&(rxArg$, rxTemplate$, msgNode& + Node_sizeof + 4)
- IF rda& THEN
- POKEL msgNode& + Node_sizeof, rda&
- AddTail errList&, msgNode&
- INCR numlines
- ELSE
- LibFreeVecPooled pool&, msgNode&
- END IF
- END IF
- END IF
- END FUNCTION
-
- ' Render a single line of text at a given position
- SUB RenderLine(BYVAL x, BYVAL y, BYVAL w, BYVAL l&)
- STATIC ltext$, prxArgs&, llen, rp&
- SHARED columnsVisible, fntHeight
-
- IF l& = currentLine& THEN
- rp& = VARPTR(selren(0))
- ELSE
- rp& = VARPTR(render(0))
- END IF
-
- Move rp&, x, y ' move the cursor to the position
-
- prxArgs& = l& + Node_sizeof + 4
- ltext$ = PEEK$(FilePart&(PEEKL(prxArgs& + 1 * 4))) + "(" + _
- PEEK$(FilePart&(PEEKL(prxArgs& + 0 * 4))) + "):" + _
- LTRIM$(STR$(PEEKL(PEEKL(prxArgs& + 2 * 4)))) + ":" + _
- PEEK$(PEEKL(prxArgs& + 6 * 4)) + STR$(PEEKL(PEEKL(prxArgs& + 7 * 4))) + " """ + _
- PEEK$(PEEKL(prxArgs& + 8 * 4)) + """"
- llen = LEN(ltext$)
-
- IF llen > columnsVisible THEN ' is line is longer than allowed?
- llen = columnsVisible ' yes, so reduce its length
- END IF
-
- Text rp&, SADD(ltext$), llen ' write to the window
-
- IF llen < columnsVisible THEN
- RectFill VARPTR(clr(0)), PEEKW(rp& + cp_x), _
- y - PEEKW(rp& + TxBaseline), _
- x + w - 1, y - PEEKW(rp& + TxBaseline) + fntHeight - 1
- END IF
- END SUB
-
- FUNCTION firstVisibleLine&
- STATIC l&, i
-
- IF PEEKL(errList& + lh_TailPred) == errList& THEN
- ' no nodes
- firstVisibleLine& = NULL&
- ELSE
- l& = PEEKL(errList& + lh_Head)
- i = topLine&
- WHILE PEEKL(l& + ln_Succ) AND i <> 0
- DECR i
- l& = PEEKL(l& + ln_Succ)
- WEND
- firstVisibleLine& = l&
- END IF
- END FUNCTION
-
- ' This function performs most of the rendering work needed by our sample.
- ' It first locks the window's layer to insure it doesn't get sized during
- ' the rendering process. It then looks at the current window size and
- ' adjusts its rendering variables in consequence. If the damage parameter
- ' is set to TRUE, the routine then proceeds to explicitly erase any area
- ' of the display to which we will not be rendering in the rendering loop.
- ' This erases any left over characters that could be left if the user sizes
- ' the window smaller. Finally, the routine determines which lines of the
- ' display need to be updated and goes on to do it.
- '
- SUB RefreshView(BYVAL damage)
- STATIC i, x, y, l&
- STATIC fontWidth, viewHeight, viewWidth, usefulWidth, usefulHeight
- SHARED columnsVisible, fntHeight
- SHARED win&
- STATIC oldTopLine&
-
- ' lock the window's layer so its size will not change
- LockLayer NULL&, PEEKL(win& + WLayer)
-
- ' determine various values based on the current size of the window
- viewWidth = PEEKW(win& + WindowWidth) - PEEKB(win& + BorderLeft) - PEEKB(win& + BorderRight)
- fontWidth = PEEKW(PEEKL(PEEKL(win& + RPort) + RastPortFont) + tf_XSize)
- columnsVisible = viewWidth \ fontWidth
-
- viewHeight = PEEKW(win& + WindowHeight) - PEEKB(win& + BorderTop) - PEEKB(win& + BorderBottom)
- linesVisible = viewHeight \ fntHeight
-
- usefulWidth = columnsVisible * fontWidth
-
- IF linesVisible > numLines THEN
- usefulHeight = numLines * fntHeight
- topLine& = 0
- ELSEIF topLine& + linesVisible > numLines THEN
- topLine& = numLines - linesVisible
- usefulHeight = (numLines - topLine&) * fntHeight
- ELSE
- usefulHeight = linesVisible * fntHeight
- END IF
-
- ' if we were called because of damage, we must erase any left over garbage
- IF damage <> FALSE& THEN
- ' erase anything left over on the right side of the window
- IF PEEKB(win& + BorderLeft) + usefulWidth < PEEKW(win& + WindowWidth) - PEEKB(win& + BorderRight) AND _
- usefulHeight <> 0 THEN
- RectFill VARPTR(clr(0)), PEEKB(win& + BorderLeft) + usefulWidth, _
- PEEKB(win& + BorderTop), _
- PEEKW(win& + WindowWidth) - PEEKB(win& + BorderRight) - 1, _
- PEEKB(win& + BorderTop) + usefulHeight - 1
- END IF
-
- ' erase anything left over on the bottom of the window
- IF (PEEKB(win& + BorderLeft) < PEEKW(win& + WindowWidth) - PEEKB(win& + BorderRight)) AND _
- (PEEKB(win& + BorderTop) + usefulHeight < PEEKW(win& + WindowHeight) - PEEKB(win& + BorderBottom)) THEN
- RectFill VARPTR(clr(0)), PEEKB(win& + BorderLeft), _
- PEEKB(win& + BorderTop) + usefulHeight, _
- PEEKW(win& + WindowWidth) - PEEKB(win& + BorderRight) - 1, _
- PEEKW(win& + WindowHeight) - PEEKB(win& + BorderBottom) - 1
- END IF
- END IF
-
- ' if we have at least one line and one column to render...
- IF usefulHeight <> 0 AND usefulWidth <> 0 THEN
- ' get a pointer to the first line currently visible
- l& = firstVisibleLine&
-
- IF damage <> FALSE& OR _
- (topLine& >= oldTopLine& + linesVisible - 1) OR _
- ((oldTopLine& > linesVisible) AND (topLine& <= oldTopLine& - linesVisible + 1)) THEN
- ' the whole display must be redrawn
- x = PEEKB(win& + BorderLeft)
- y = PEEKB(win& + BorderTop) + PEEKW(PEEKL(PEEKL(win& + RPort) + RastPortFont) + tf_Baseline)
- i = linesVisible
- ELSEIF topLine& < oldTopLine& THEN
- ' we just need to scroll the text
- ScrollRaster VARPTR(render(0)), 0, -((oldTopLine& - topLine&) * fntHeight), _
- PEEKB(win& + BorderLeft), _
- PEEKB(win& + BorderTop), _
- PEEKB(win& + BorderLeft) + usefulWidth - 1, _
- PEEKB(win& + BorderTop) + usefulHeight - 1 _
-
- ' indicates what section needs to be redrawn
- x = PEEKB(win& + BorderLeft)
- y = PEEKB(win& + BorderTop) + PEEKW(PEEKL(PEEKL(win& + RPort) + RastPortFont) + tf_Baseline)
- i = oldTopLine& - topLine&
- ELSEIF topLine& > oldTopLine& THEN
- ' we just need to scroll the text
- ScrollRaster VARPTR(render(0)), 0, (topLine& - oldTopLine&) * fntHeight, _
- PEEKB(win& + BorderLeft), _
- PEEKB(win& + BorderTop), _
- PEEKB(win& + BorderLeft) + usefulWidth - 1, _
- PEEKB(win& + BorderTop) + usefulHeight - 1
-
- ' indicates what section needs to be redrawn
- i = linesVisible - (topLine& - oldTopLine&)
- WHILE PEEKL(l& + ln_Succ) AND i <> 0
- DECR i
- l& = PEEKL(l& + ln_Succ)
- WEND
-
- x = PEEKB(win& + BorderLeft)
- y = PEEKB(win& + BorderTop) + _
- PEEKW(PEEKL(PEEKL(win& + RPort) + RastPortFont) + tf_Baseline) + _
- (fntHeight * (linesVisible - (topLine& - oldTopLine&)))
- i = topLine& - oldTopLine&
- ELSE
- ' we don't need to render anything
- i = 0
- END IF
-
- ' render all the lines we need
- WHILE PEEKL(l& + ln_Succ) AND i <> 0
- DECR i
- RenderLine x, y, usefulWidth, l&
- y = y + fntHeight
- l& = PEEKL(l& + ln_Succ)
- WEND
- END IF
-
- ' unlock the layer so normal operations can resume
- UnlockLayer PEEKL(win& + WLayer)
-
- ' keep track of what the current top line is. That way, when we
- ' come back in this routine later, and "topLine" has changed, we
- ' can tell how many lines we need to scroll in order to sync up the
- ' display
- oldTopLine& = topLine&
- END SUB
-
- ' This is the message packet passed by layers.library to a backfill hook.
- ' It contains a pointer to the layer that has been damaged, a Rectangle
- ' structure that defines the bounds of the damage. No rendering can occur
- ' outside of these coordinates.
- '
- ' The backfill hook is also passed a RastPort in which the rendering
- ' should be performed
-
- CONST bf_Layer = 0
- CONST bf_Bounds = 4
- CONST bf_OffsetX = 8
- CONST bf_OffsetY = 12
- CONST BackFillMsg_sizeof = 16
-
- SUB BackFillHook(BYVAL hook&, BYVAL rp&, BYVAL bfm&)
- LOCAL crp&
- SHARED taskBusy
-
- crp& = AllocMem&(RastPort_sizeof, MEMF_ANY&)
- IF crp& <> NULL& THEN
- CopyMem rp&, crp&, RastPort_sizeof ' copy the rastport
- POKEL crp& + Layer, NULL& ' eliminate bogus clipping from our copy
-
- IF taskBusy = TRUE& THEN
- SafeSetWriteMask crp&, &hFF ' if the main task is busy, clear all planes
- ELSE
- SafeSetWriteMask crp&, &hFE ' otherwise, clear all planes except plane 0
- END IF
-
- SetAPen crp&, 0 ' set the pen to color 0
- SetDrMd crp&, JAM2& ' set the rendering mode we need
-
- ' clear the whole area
- RectFill crp&, PEEKW(bfm& + bf_Bounds + RectangleMinX), _
- PEEKW(bfm& + bf_Bounds + RectangleMinY), _
- PEEKW(bfm& + bf_Bounds + RectangleMaxX), _
- PEEKW(bfm& + bf_Bounds + RectangleMaxY)
- FreeMem crp&, RastPort_sizeof
- END IF
- END SUB
-
- FUNCTION newVScroller&(BYVAL bottomspace)
- STATIC sizeim&, height, proplgap, proprgap, lt, borderless&
- SHARED dri&, scr&, sizeim&
-
- ' guesstimate the resolution
- proplgap = PROP_LGAP_LOWRES
- proprgap = PROP_RGAP_LOWRES
- IF PEEKW(dri& + DrawInfoX) <= 22 THEN
- proplgap = PROP_LGAP_MEDRES
- proprgap = PROP_RGAP_MEDRES
- END IF
-
- ' take into account the Workbench look for sliders
- IF PEEKW(LIBRARY("intuition.library") + IntuitionBaseLibNode + lib_Version) >= 39 THEN
- borderless& = TRUE&
- ELSE
- borderless& = FALSE&
- END IF
-
- ' generate the scroll gadget
- height = PEEKB(scr& + WBorTop) + PEEKW(PEEKL(scr& + ScreenFont) + ta_YSize) + 1
- lt = height + PROP_VGAP
- TAGLIST VARPTR(tl&(0)), _
- GA_Top&, lt, _
- GA_Width&, PEEKW(sizeim& + ImageWidth) - proplgap - proprgap, _
- GA_RelRight&, -PEEKW(sizeim& + ImageWidth) + proplgap + 1, _
- GA_RelHeight&, -(bottomspace + lt + PEEKW(sizeim& + ImageHeight) + PEEKB(scr& + WBorBottom) + PROP_VGAP - 2), _
- GA_RightBorder&, TRUE&, _
- PGA_NewLook&, TRUE&, _
- PGA_Borderless&, borderless&, _
- PGA_Freedom&, FREEVERT&, _
- PGA_Total&, 1, _
- PGA_Visible&, 1, _
- PGA_Top&, 0, _
- TAG_END&
-
- newVScroller& = NewObjectA&(NULL&, SADD("propgclass" + CHR$(0)), VARPTR(tl&(0)))
- END FUNCTION
-
- ' Adjust the scroller object to reflect the current window size and
- ' scroll offset within our document
- SUB SetScroller(BYVAL win&, BYVAL scroller&, _
- BYVAL linesVisible&, BYVAL numLines&, BYVAL topLines&)
- TAGLIST VARPTR(tl&(0)), _
- PGA_Visible&, linesVisible&, _
- PGA_Total&, numLines&, _
- PGA_Top&, topLine&, _
- TAG_END&
-
- junk& = SetGadgetAttrsA&(scroller&, win&, NULL&, VARPTR(tl&(0)))
- END SUB
-
- SUB BusyState(BYVAL makeBusy)
- SHARED taskBusy, win&
-
- taskBusy = makeBusy
- IF makeBusy = FALSE& THEN
- normalPointer win&
- ELSE
- busyPointer win&
- END IF
- IF PEEKW(PEEKL(win& + WLayer) + LayerFlags) AND LAYERREFRESH& THEN
- BeginRefresh win&
- RefreshView TRUE&
- EndRefresh win&, TRUE&
- END IF
- END SUB
-
- SUB deltaLine(BYVAL n)
- IF currentLine& <> NULL& THEN
- IF n > 0 THEN
- DO WHILE PEEKL(PEEKL(currentLine& + ln_Succ) + ln_Succ) <> NULL& AND _
- n <> 0
- DECR n
- currentLine& = PEEKL(currentLine& + ln_Succ)
- LOOP WHILE PEEKL(currentLine& + ln_Succ) <> NULL&
- ELSEIF n < 0 THEN
- DO WHILE PEEKL(PEEKL(currentLine& + ln_Pred) + ln_Pred) <> NULL& AND _
- n <> 0
- INCR n
- currentLine& = PEEKL(currentLine& + ln_Pred)
- LOOP WHILE PEEKL(currentLine& + ln_Pred) <> NULL&
- END IF
- RefreshView TRUE&
- END IF
- END SUB
-
- CONST VSCROLLERGA_ID = 1 ' arbitrary gadget IDs for scroller gadgets
- CONST VSCROLLUPGA_ID = 2
- CONST VSCROLLDOWNGA_ID = 3
-
- DIM kbuf(7) ' no more than 16 bytes
- DIM ie(InputEvent_sizeof \ 2)
-
- SUB handleSignals
- STATIC msg&, done, sigMask&, sigs&, actual, ckey, n, l&, gotoLine&
- STATIC intuiMsgClass&, intuiMsgCode, intuiMsgMouseX, intuiMsgMouseY
- STATIC leftSeconds&, leftMicros&, intuiMsgSeconds&, intuiMsgMicros&
- STATIC prxArgs&
- SHARED win&, vscroller&, rxPort&, fntHeight
- SHARED kbuf(), ie()
-
- ' prepare the InputEvent structure
- POKEB VARPTR(ie(0)) + ie_Class, IECLASS_RAWKEY&
- POKEB VARPTR(ie(0)) + ie_SubClass, 0
-
- ' render the initial display
- RefreshView TRUE&
-
- sigMask& = 1& << PEEKB(PEEKL(win& + UserPort) + mp_SigBit)
- sigMask& = sigMask& OR (1& << PEEKB(rxPort& + mp_SigBit))
-
- done = FALSE&
- BusyState FALSE&
- WHILE done = FALSE&
- ' if the LAYERREFRESH flag is set in the window's
- ' layer, it means the layer has some damage we
- ' should repair.
- IF PEEKW(PEEKL(win& + WLayer) + LayerFlags) AND LAYERREFRESH& THEN
- ' enter optimized repair state
- BeginRefresh win&
-
- ' redraw the whole display through the optimized repair
- ' region
- RefreshView TRUE&
-
- ' tell the system we are done repairing the window
- EndRefresh win&, TRUE&
- END IF
-
- sigs& = xWait&(sigMask&)
- gotoLine& = NULL&
- IF sigs& AND (1& << PEEKB(PEEKL(win& + UserPort) + mp_SigBit)) THEN
- msg& = GetMsg&(PEEKL(win& + UserPort))
- WHILE msg& <> NULL&
- intuiMsgClass& = PEEKL(msg& + Class)
- intuiMsgCode = PEEKW(msg& + IntuiMessageCode)
- intuiMsgSeconds& = PEEKL(msg& + IntuiMessageSeconds)
- intuiMsgMicros& = PEEKL(msg& + IntuiMessageMicros)
- intuiMsgMouseX = PEEKW(msg& + IntuiMessageMouseX)
- intuiMsgMouseY = PEEKW(msg& + IntuiMessageMouseY)
-
- ' map RawKeys to ANSI codes
- IF intuiMsgClass& = IDCMP_RAWKEY& THEN
- ' need to convert the RawKey before replying
-
- POKEW VARPTR(ie(0)) + ie_Code, intuiMsgCode
- POKEW VARPTR(ie(0)) + ie_Qualifier, PEEKW(msg& + Qualifier)
- ' recover dead key codes & qualifiers
- POKEL VARPTR(ie(0)) + ie_addr, PEEKL(msg& + IAddress)
- actual = MapRawKey&(VARPTR(ie(0)), VARPTR(kbuf(0)), 16, NULL&)
- END IF
-
- ReplyMsg msg&
-
- SELECT CASE intuiMsgClass&
- CASE IDCMP_CLOSEWINDOW&
- ' user clicked on the close gadget, exit the program
- done = TRUE&
-
- CASE IDCMP_NEWSIZE&
- ' user sized the window. We need to redraw the whole
- ' display in order to eliminate any garbage. Start by
- ' calling BeginRefresh() and EndRefresh() to eliminate
- ' the window's damage regions then completely redraw
- ' the window contents.
-
- BeginRefresh win&
- EndRefresh win&, TRUE&
- RefreshView TRUE&
- SetScroller win&, vscroller&, linesVisible, numLines, topLine&
-
- CASE IDCMP_REFRESHWINDOW&
- ' Intuition is telling us damage occured to our layer.
- ' Don't bother doing anything, the check at the top of the
- ' loop will catch this fact and refresh the display
- '
- ' Even though we don't do anything with these events, we
- ' still need them to be sent to us so we will wake up and
- ' look at the LAYERREFRESH bit.
-
- CASE IDCMP_RAWKEY&:
- ' decode the keystroke
-
- SELECT CASE actual
- CASE 1
- ckey = PEEKB(VARPTR(kbuf(0))) AND &hFF
- SELECT CASE ckey
- CASE &h0D ' CR
- gotoLine& = currentLine&
- END SELECT
-
- CASE 2
- ckey = kbuf(0)
- n = 0
- SELECT CASE ckey
- CASE &h9B41 ' cursor up
- n = -1
-
- CASE &h9B42 ' cursor down
- n = 1
-
- CASE &h9B54 ' shift cursor up
- n = -(linesVisible - 1)
-
- CASE &h9B53 ' shift cursor down
- n = linesVisible - 1
- END SELECT
- IF n <> 0 THEN
- deltaLine n
- END IF
- END SELECT
-
- CASE IDCMP_MOUSEBUTTONS&
- IF intuiMsgCode = SELECTDOWN& THEN
- n = (intuiMsgMouseY - PEEKB(win& + BorderTop)) \ fntHeight
- IF n < 0 THEN
- n = 0
- ELSEIF n >= linesVisible THEN
- n = linesVisible - 1
- END IF
- currentLine& = firstVisibleLine&
- deltaLine n
- IF DoubleClick(leftSeconds&, leftMicros&, _
- intuiMsgSeconds&, intuiMsgMicros&) THEN
- gotoLine& = currentLine&
- leftSeconds& = 0
- leftMicros& = 0
- ELSE
- leftSeconds& = intuiMsgSeconds&
- leftMicros& = intuiMsgMicros&
- END IF
- END IF
-
- CASE IDCMP_IDCMPUPDATE&
- SELECT CASE intuiMsgCode
- CASE VSCROLLERGA_ID
- ' user is playing with the scroller. Get the
- ' scroller's current top line and synchronize
- ' the display to match it
-
- junk& = GetAttr&(PGA_Top&, vscroller&, VARPTR(topLine&))
- RefreshView FALSE&
-
- CASE VSCROLLUPGA_ID
- ' click on the up gadget, act on it if enough lines
- ' available
- IF topLine& > 0 THEN
- DECR topLine&
- ' update the top line
- TAGLIST VARPTR(tl&(0)), _
- PGA_Top&, topLine&, _
- TAG_END&
- junk& = SetGadgetAttrsA&(vscroller&, win&, NULL&, VARPTR(tl&(0)))
- RefreshView FALSE&
- END IF
-
- CASE VSCROLLDOWNGA_ID
- ' click on the down gadget, act on it if enough lines
- ' available
- IF topLine& + linesVisible < numLines THEN
- INCR topLine&
- ' update the top line
- TAGLIST VARPTR(tl&(0)), _
- PGA_Top&, topLine&, _
- TAG_END&
- junk& = SetGadgetAttrsA&(vscroller&, win&, NULL&, VARPTR(tl&(0)))
- RefreshView FALSE&
- END IF
- END SELECT
- END SELECT
- IF gotoLine& <> NULL& THEN
- prxArgs& = gotoLine& + Node_sizeof + 4
-
- ' start the NewMsg script with the original parameters
- junk& = issueRXCommand&(rxPort&, _
- "NewMsg " + _
- """" + PEEK$(PEEKL(prxArgs& + 0 * 4)) + """" + " " + _
- """" + PEEK$(PEEKL(prxArgs& + 1 * 4)) + """" + " " + _
- LTRIM$(STR$(PEEKL(PEEKL(prxArgs& + 2 * 4)))) + " " + _
- LTRIM$(STR$(PEEKL(PEEKL(prxArgs& + 3 * 4)))) + " " + _
- """" + PEEK$(PEEKL(prxArgs& + 4 * 4)) + """" + " " + _
- LTRIM$(STR$(PEEKL(PEEKL(prxArgs& + 5 * 4)))) + " " + _
- """" + PEEK$(PEEKL(prxArgs& + 6 * 4)) + """" + " " + _
- LTRIM$(STR$(PEEKL(PEEKL(prxArgs& + 7 * 4)))) + " " + _
- """" + PEEK$(PEEKL(prxArgs& + 8 * 4)) + """", _
- "rexx")
- END IF
- msg& = GetMsg&(PEEKL(win& + UserPort))
- WEND
- END IF
- IF sigs& AND (1& << PEEKB(rxPort& + mp_SigBit)) THEN
- BusyState TRUE&
- msg& = GetMsg&(rxPort&)
- WHILE msg& <> NULL&
- IF PEEKB(msg& + rm_Node + mn_Node + ln_Type) = NT_REPLYMSG& THEN
- disposeRXCommand rxPort&, msg&
- ELSE
- done = dispatchRXMsg(PEEK$(PEEKL(msg& + rm_Args)))
- ReplyMsg msg&
- END IF
- msg& = GetMsg&(rxPort&)
- WEND
- BusyState FALSE&
-
- IF PEEKW(PEEKL(win& + WLayer) + LayerFlags) AND LAYERREFRESH& THEN
- ' eat the refresh if there was one pending
- BeginRefresh win&
- EndRefresh win&, TRUE&
- END IF
- RefreshView TRUE& ' refresh for the new string
-
- ' update the slider size
- TAGLIST VARPTR(tl&(0)), _
- PGA_Total&, numLines, _
- TAG_END&
-
- junk& = SetGadgetAttrsA&(vscroller&, win&, NULL&, VARPTR(tl&(0)))
- END IF
- WEND
- END SUB
-
- DIM refreshHook(Hook_sizeof \ 2)
- DIM icaGaIdToICSpecial&(2)
-
- FUNCTION main(BYVAL template&)
- STATIC node&, driFillPen, wrMask, currentPos&, currentLength&, rdArgs&, myRDArgs&
- STATIC msg&, wbArg&, diskObj&, tmplock&, toolTypes&, totalString&, totalSize&, r
- SHARED scr&, dri&, win&, rxPort&, refreshHook(), icaGaIdToICSpecial&()
- SHARED vscroller&, vupbutton&, vdownbutton&, sizeim&, upim&, downim&
- SHARED taskBusy, fntHeight
-
- r = RETURN_FAIL&
-
- ' find out if WB or CLI launched
- msg& = PEEKL(SYSTAB + 8)
- IF msg& <> NULL& THEN
- ' Started from Workbench so do icon magic...
- '
- ' What we will do here is try all of the tooltypes
- ' in the icon and keep only those which do not cause
- ' errors in the RDArgs.
-
- wbArg& = PEEKL(msg& + sm_ArgList)
-
- ' Use project icon if it is there...
- IF PEEKL(msg& + sm_NumArgs) > 1 THEN
- wbArg& = wbArg& + 4
- END IF
-
- tmplock& = CurrentDir&(PEEKL(wbArg& + wa_Lock))
- diskObj& = GetDiskObject&(PEEKL(wbArg& + wa_Name))
- IF diskObj& <> NULL& THEN
- toolTypes& = PEEKL(diskObj& + do_ToolTypes)
- IF toolTypes& <> NULL& THEN
- totalSize& = 3
-
- WHILE PEEKL(toolTypes&)
- totalSize& = totalSize& + LEN(PEEK$(PEEKL(toolTypes&))) + 1
- toolTypes& = toolTypes& + 4
- WEND
-
- totalString& = LibAllocPooled&(pool&, totalSize&)
- IF totalString& <> NULL& THEN
- currentPos& = totalString&
- toolTypes& = PEEKL(diskObj& + do_ToolTypes)
- DO
- POKEB currentPos&, 0
- IF PEEKL(toolTypes&) THEN
- CopyMem PEEKL(toolTypes&), currentPos&, LEN(PEEK$(PEEKL(toolTypes&)))
- END IF
- currentLength& = LEN(PEEK$(currentPos&))
- POKEB currentPos& + currentLength& + 0, &h0A
- POKEB currentPos& + currentLength& + 1, &h00
-
- IF rdargs& THEN
- FreeArgs rdargs&
- END IF
- rdargs& = NULL&
-
- IF myRDArgs& <> NULL& THEN
- FreeDosObject DOS_RDARGS&, myRDArgs&
- END IF
- myRDArgs& = AllocDosObject&(DOS_RDARGS&, NULL&)
- IF myRDArgs& <> NULL& THEN
- POKEL myRDArgs& + RDA_Source + CS_Buffer, totalString&
- POKEL myRDArgs& + RDA_Source + CS_Length, LEN(PEEK$(totalString&))
-
- rdargs& = ReadArgs&(template&, VARPTR(opts&(0)), myRDArgs&)
- IF rdargs& <> NULL& THEN
- POKEB currentPos& + currentLength&, ASC(" ")
- currentPos& = currentPos& + currentLength& + 1
- END IF
- END IF
- toolTypes& = toolTypes& + 4
- LOOP WHILE PEEKL(toolTypes& - 4) <> NULL&
- LibFreePooled pool&, totalString&, totalSize&
- END IF
- END IF
- FreeDiskObject diskObj&
- END IF
- junk& = CurrentDir&(tmplock&)
- r = RETURN_OK&
- ELSE
- ' Started from CLI so do standard ReadArgs
-
- rdargs& = ReadArgs&(template&, VARPTR(opts&(0)), NULL&)
- IF rdargs& = NULL& THEN
- junk& = PrintFault&(IoErr&, NULL&)
- ELSEIF SetSignal&(0, 0) AND SIGBREAKF_CTRL_C& THEN
- junk& = PrintFault&(ERROR_BREAK&, NULL&)
- ELSE
- r = RETURN_OK&
- END IF
- END IF
-
- IF r = RETURN_OK& THEN
- r = RETURN_FAIL&
-
- ' Allocate a list to store the message nodes
- errList& = LibAllocPooled&(pool&, List_sizeof)
- NewList errList&
-
- scr& = LockPubScreen&(opts&(OPT_PUBSCREEN))
- IF scr& = NULL& THEN
- ' fall back to the Workbench screen
- scr& = LockPubScreen&(NULL&)
- END IF
- IF scr& <> NULL& THEN
- dri& = GetScreenDrawInfo&(scr&)
- IF dri& <> NULL& THEN
- ' obtain a size gadget image (for metric purposes)
- TAGLIST VARPTR(tl&(0)), _
- SYSIA_Which&, SIZEIMAGE&, _
- SYSIA_DrawInfo&, dri&, _
- TAG_END&
- sizeim& = NewObjectA&(NULL&, SADD("sysiclass" + CHR$(0)), VARPTR(tl&(0)))
-
- ' obtain a up arrow image
- TAGLIST VARPTR(tl&(0)), _
- SYSIA_Which&, UPIMAGE&, _
- SYSIA_DrawInfo&, dri&, _
- TAG_END&
- upim& = NewObjectA&(NULL&, SADD("sysiclass" + CHR$(0)), VARPTR(tl&(0)))
-
- ' obtain a down arrow image
- TAGLIST VARPTR(tl&(0)), _
- SYSIA_Which&, DOWNIMAGE&, _
- SYSIA_DrawInfo&, dri&, _
- TAG_END&
- downim& = NewObjectA&(NULL&, SADD("sysiclass" + CHR$(0)), VARPTR(tl&(0)))
-
- IF sizeim& <> NULL& AND upim& <> NULL& AND downim& <> NULL& THEN
- vscroller& = newVScroller&(PEEKW(upim& + ImageHeight) + PEEKW(downim& + ImageHeight))
- IF vscroller& <> NULL& THEN
- ' ICA_MAP to stuff gadget ID into the IntuiMessageCode field
- TAGLIST VARPTR(icaGaIdToICSpecial&(0)), _
- GA_ID&, ICSPECIAL_CODE&, _
- TAG_END&
-
- ' connect the scroller to the IDCMP
- TAGLIST VARPTR(tl&(0)), _
- GA_ID&, VSCROLLERGA_ID, _
- ICA_TARGET&, ICTARGET_IDCMP&, _
- ICA_MAP&, VARPTR(icaGaIdToICSpecial&(0)), _
- TAG_END&
- junk& = SetAttrsA&(vscroller&, VARPTR(tl&(0)))
-
- ' create up button
- TAGLIST VARPTR(tl&(0)), _
- GA_ID&, VSCROLLUPGA_ID, _
- GA_Image&, upim&, _
- GA_RelBottom&, -(PEEKW(sizeim& + ImageHeight) + PEEKW(upim& + ImageHeight) + PEEKW(downim& + ImageHeight)) + 1, _
- GA_Width&, PEEKW(upim& + ImageWidth), _
- GA_RelRight&, -PEEKW(upim& + ImageWidth) + 1, _
- GA_Height&, -PEEKW(upim& + ImageHeight) + 1, _
- GA_Highlight&, GFLG_GADGHIMAGE&, _
- GA_RightBorder&, TRUE&, _
- ICA_TARGET&, ICTARGET_IDCMP&, _
- ICA_MAP&, VARPTR(icaGaIdToICSpecial&(0)), _
- GA_Previous&, vscroller&, _
- TAG_END&
- vupbutton& = NewObjectA(NULL&, SADD("buttongclass" + CHR$(0)), VARPTR(tl&(0)))
-
- ' create down button
- TAGLIST VARPTR(tl&(0)), _
- GA_ID&, VSCROLLDOWNGA_ID, _
- GA_Image&, downim&, _
- GA_RelBottom&, -(PEEKW(sizeim& + ImageHeight) + PEEKW(downim& + ImageHeight)) + 1, _
- GA_Width&, PEEKW(downim& + ImageWidth), _
- GA_RelRight&, -PEEKW(downim& + ImageWidth) + 1, _
- GA_Height&, -PEEKW(downim& + ImageHeight) + 1, _
- GA_Highlight&, GFLG_GADGHIMAGE&, _
- GA_RightBorder&, TRUE&, _
- ICA_TARGET&, ICTARGET_IDCMP&, _
- ICA_MAP&, VARPTR(icaGaIdToICSpecial&(0)), _
- GA_Previous&, vupbutton&, _
- TAG_END&
- vdownbutton& = NewObjectA(NULL&, SADD("buttongclass" + CHR$(0)), VARPTR(tl&(0)))
-
- IF vupbutton& <> NULL& AND vdownbutton& <> NULL& THEN
- ' initialise an optimized backfill hook
- INITHOOK VARPTR(refreshHook(0)), VARPTRS(BackFillHook)
- TAGLIST VARPTR(tl&(0)), _
- WA_PubScreen&, scr&, _
- WA_AutoAdjust&, TRUE&, _
- WA_CloseGadget&, TRUE&, _
- WA_DepthGadget&, TRUE&, _
- WA_DragBar&, TRUE&, _
- WA_SizeGadget&, TRUE&, _
- WA_SizeBRight&, TRUE&, _
- WA_SimpleRefresh&, TRUE&, _
- WA_Activate&, TRUE&, _
- WA_Gadgets&, vscroller&, _
- WA_MinWidth&, PEEKW(sizeim& + ImageWidth) * 5, _
- WA_MinHeight&, _
- PEEKW(sizeim& + ImageWidth) + _
- PEEKW(upim& + ImageWidth) + _
- PEEKW(downim& + ImageWidth) + _
- (PEEKW(PEEKL(scr& + ScreenFont) + ta_YSize) + 1) * 2, _
- WA_MaxWidth&, -1, _
- WA_MaxHeight&, -1, _
- WA_NewLookMenus&, TRUE&, _
- WA_IDCMP&, _
- IDCMP_CLOSEWINDOW& OR _
- IDCMP_NEWSIZE& OR _
- IDCMP_REFRESHWINDOW& OR _
- IDCMP_RAWKEY& OR _
- IDCMP_MOUSEBUTTONS& OR _
- IDCMP_IDCMPUPDATE&, _
- WA_BackFill&, VARPTR(refreshHook(0)), _
- TAG_END&
-
- taskBusy = TRUE&
- win& = OpenWindowTagList&(NULL&, VARPTR(tl&(0)))
- IF win& <> NULL& THEN
- fntHeight = PEEKW(PEEKL(PEEKL(win& + RPort) + RastPortFont) + tf_YSize)
- driFillPen = PEEKW(PEEKL(dri& + dri_Pens) + FILLPEN& * 2)
-
- ' initialize rendering attributes we are going to use
- CopyMem PEEKL(win& + RPort), VARPTR(render(0)), RastPort_sizeof
- SetDrMd VARPTR(render(0)), JAM2&
- SetAPen VARPTR(render(0)), PEEKW(PEEKL(dri& + dri_Pens) + TEXTPEN& * 2)
-
- ' initialize selected rendering attributes
- CopyMem PEEKL(win& + RPort), VARPTR(selren(0)), RastPort_sizeof
- SetDrMd VARPTR(selren(0)), JAM2&
- SetAPen VARPTR(selren(0)), PEEKW(PEEKL(dri& + dri_Pens) + FILLTEXTPEN& * 2)
- SetBPen VARPTR(selren(0)), driFillPen
-
- ' initialize clearing attributes we are going to use
- CopyMem PEEKL(win& + RPort), VARPTR(clr(0)), RastPort_sizeof
- SetDrMd VARPTR(clr(0)), JAM2&
- SetAPen VARPTR(clr(0)), PEEKW(PEEKL(dri& + dri_Pens) + BACKGROUNDPEN& * 2)
-
- ' set write masks for the RastPorts
- IF PEEKW(PEEKL(dri& + dri_Pens) + FILLTEXTPEN& * 2) > driFillPen THEN
- driFillPen = PEEKW(PEEKL(dri& + dri_Pens) + FILLTEXTPEN& * 2)
- END IF
- IF PEEKW(LIBRARY("graphics.library") + GfxBaseLibNode + lib_Version) >= 39 THEN
- SetMaxPen VARPTR(render(0)), driFillPen
- SetMaxPen VARPTR(selren(0)), driFillPen
- SetMaxPen VARPTR(clr(0)), driFillPen
- ELSE
- ' compute the write mask with driFillPen as the
- ' maximum pen
- DO
- wrMask = driFillPen AND -driFillPen
- driFillPen = driFillPen AND NOT wrMask
- LOOP UNTIL driFillPen = 0
- wrMask = (1 << wrMask) - 1
- SetWrMsk VARPTR(render(0)), wrMask
- SetWrMsk VARPTR(selren(0)), wrMask
- SetWrMsk VARPTR(clr(0)), wrMask
- END IF
-
- IF opts&(OPT_PORTNAME) <> NULL& THEN
- rxPort& = createRXPort&(opts&(OPT_PORTNAME))
- ELSE
- rxPort& = createRXPort&(SADD("HBMSG" + CHR$(0)))
- END IF
- IF rxPort& <> NULL& THEN
- ' handle the programs events
- handleSignals
-
- BusyState TRUE&
- ' dispose of all remaining nodes on the error list
- node& = RemHead&(errList&)
- WHILE node& <> NULL&
- disposeRXArgs PEEKL(node& + Node_sizeof)
- LibFreeVecPooled pool&, node&
- node& = RemHead&(errList&)
- WEND
- main = RETURN_OK&
- disposeRXPort rxPort&
- END IF
- CloseWindow win&
- END IF
- DisposeObject vupbutton&
- DisposeObject vdownbutton&
- END IF
- DisposeObject vscroller&
- END IF
- END IF
- DisposeObject downim& ' DisposeObject NULL& is safe
- DisposeObject upim&
- DisposeObject sizeim&
- FreeScreenDrawInfo scr&, dri&
- END IF
- UnlockPubScreen NULL&, scr&
- END IF
- END IF
- IF rdargs& THEN
- FreeArgs rdargs&
- END IF
- IF myRDArgs& THEN
- FreeDosObject DOS_RDARGS&, myRDArgs&
- END IF
- main = r
- END FUNCTION
-
- allocBusyPointer
- pool& = LibCreatePool&(MEMF_ANY& OR MEMF_CLEAR&, 8192, 4096) ' create a pool for our allocations
- IF pool& <> NULL& THEN
- r = main(SADD("PUBSCREEN/K,PORTNAME/K" + CHR$(0)))
- LibDeletePool pool& ' takes all allocated memory with it
- ELSE
- r = RETURN_FAIL
- END IF
- freeBusyPointer
- SYSTEM r
-